package ch01.text00.tx11.demo01;

import java.lang.reflect.Field;

/**
 * @author V
 * @date 2025-03-24
 */
public class BeanUtil {
    /**
     * 1、设置何意对象的属性值
     *
     * @param bean         Bean对象
     * @param propertyName 属性名称
     * @param value        属性值
     */
    public static void setProperty(Object bean, String propertyName, Object value) {
        // 第一：获取操作类的 Class 对象
        Class<?> clazz = bean.getClass();

        try {
            // 第二：获取 Bean 对象的字段对象
            Field field = clazz.getDeclaredField(propertyName);

            // 第三：开放访问权限
            field.setAccessible(true);

            // 第四：调用 setXxx 方法，实现初始化工作
            field.set(bean, value);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException("未知字段", e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("初始化属性失败", e);
        }

    }

    /**
     * 2、获取任意对象的属性值
     *
     * @param bean         Bean对象
     * @param propertyName 属性名称
     * @return 属性值
     */
    public static Object getProperty(Object bean, String propertyName) {
        // 第一：获取操作类的 Class 对象
        Class<?> clazz = bean.getClass();

        try {
            // 第二：获取 Bean 对象的字段对象
            Field field = clazz.getDeclaredField(propertyName);

            // 第三：开放访问权限
            field.setAccessible(true);

            // 第四：调用 getXxx 方法，获取字段数据
            return field.get(bean);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException("未知字段", e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("获取字段数据失败", e);
        }
    }

    /**
     * 3、复制某个对象的属性值到另一个对象中
     *
     * @param sourceBean 源 Bean 对象
     * @param targetBean 目标 Bean 对象
     */
    public static void copyProperties(Object sourceBean, Object targetBean) {
        // 第一：获取要操作类的 Class 对象
        Class<?> sourceBeanClass = sourceBean.getClass();
        Class<?> targetBeanClass = targetBean.getClass();

        // 第二：基于 Class 对象实现相关的操作
        // 1.获取源 Bean 对象的所有字段
        Field[] sourceFields = sourceBeanClass.getDeclaredFields();

        // 2.循环遍历源 Bean 对象的所有字段 - 获取源对象的字段值，赋值给目标对象对应的字段
        for (Field sourceField : sourceFields) {
            try {
                // 3.获取源 Bean 对象的某个字段数据
                sourceField.setAccessible(true);
                Object sourceFieldData = sourceField.get(sourceBean);

                // 4.获取源 Bean 对象的某个字段的名称
                String sourceFieldName = sourceField.getName();

                // 5.获取目标 Bean 对象对应的 Filed 对象
                Field targetField = targetBeanClass.getDeclaredField(sourceFieldName);

                // 6.开放权限
                targetField.setAccessible(true);

                // 7.拷贝赋值
                targetField.set(targetBean, sourceFieldData);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (NoSuchFieldException e) {
                throw new RuntimeException("未知字段", e);
            }
        }
    }
}
